import { useState, useEffect, useCallback } from 'react';
import { Moment } from 'moment';
import { RangeValue } from 'antd/node_modules/rc-picker/lib/interface';

export interface DomSize {
  width?: number;
  height?: number;
}

// https://codesandbox.io/s/jj61r2w6z5
export function useWindowSize() {
  // Initialize state with undefined width/height so server and client renders match
  // Learn more here: https://joshwcomeau.com/react/the-perils-of-rehydration/
  const [windowSize, setWindowSize] = useState<DomSize>({
    width: undefined,
    height: undefined,
  });

  useEffect(() => {
    // Handler to call on window resize
    function handleResize() {
      // Set window width/height to state
      setWindowSize({
        width: window.innerWidth,
        height: window.innerHeight,
      });
    }

    // Add event listener
    window.addEventListener('resize', handleResize);

    // Call handler right away so state gets updated with initial window size
    handleResize();

    // Remove event listener on cleanup
    return () => window.removeEventListener('resize', handleResize);
  }, []); // Empty array ensures that effect is only run on mount

  return windowSize;
}

// https://codesandbox.io/s/useasync-hook-rx5z2?file=/src/App.js:102-109

const useAsync = <T, E = string>(
  asyncFunction: () => Promise<T>,
  immediate = true,
) => {
  const [status, setStatus] = useState<
    'idle' | 'pending' | 'success' | 'error'
  >('idle');
  const [value, setValue] = useState<T | null>(null);
  const [error, setError] = useState<E | null>(null);

  // The execute function wraps asyncFunction and
  // handles setting state for pending, value, and error.
  // useCallback ensures the below useEffect is not called
  // on every render, but only if asyncFunction changes.
  const execute = useCallback(() => {
    setStatus('pending');
    setValue(null);
    setError(null);

    return asyncFunction()
      .then((response: any) => {
        setValue(response);
        setStatus('success');
      })
      .catch((error: any) => {
        setError(error);
        setStatus('error');
      });
  }, [asyncFunction]);

  // Call execute if we want to fire it right away.
  // Otherwise execute can be called later, such as
  // in an onClick handler.
  useEffect(() => {
    if (immediate) {
      execute();
    }
  }, [execute, immediate]);

  return { execute, status, value, error };
};

export const useDomSize = (dom?: HTMLDivElement) => {
  const [domSize, setDomSize] = useState<DomSize>({
    width: undefined,
    height: undefined,
  });

  useEffect(() => {
    // Handler to call on window resize
    function handleResize() {
      // Set window width/height to state
      setDomSize({
        width: dom?.clientWidth,
        height: dom?.clientHeight,
      });
    }

    // Add event listener
    dom?.addEventListener('resize', handleResize);

    // Call handler right away so state gets updated with initial window size
    handleResize();

    // Remove event listener on cleanup
    return () => dom?.removeEventListener('resize', handleResize);
  }, []); // Empty array ensures that effect is only run on mount

  return domSize;
};
/**
 * @description: 选择RangePicker的DisabledDate判断，开始时间只能选择今天之前
 * @param {type}
 * @return {type}
 */
export const useDisabledDate = (
  dates: RangeValue<Moment> | [] | undefined,
  current: Moment,
) => {
  if (!dates || dates.length === 0) {
    // 没有选择的时候
    return current.isAfter(new Date());
  } else {
    return false;
  }
};
/**
 * @description: 防抖
 * @param {*} T
 * @return {*}
 */
export const usePreventShake = <T>(v: T, t = 500) => {
  const [val, setval] = useState<T>(v);
  useEffect(() => {
    let Tid = setTimeout(() => {
      setval(v);
    }, t);
    return () => {
      clearTimeout(Tid);
    };
  }, [v, t]);
  return val;
};
